/*
 * s_opendoor_ctl.c
 *
 *  Created on: Nov 21, 2019
 *      Author: hemingway
 */
#include "s_opendoor_ctl.h"

#include <stdio.h>
#include <string.h>

#include "h_cc2640r2f_define.h"

#include "h_cc2640r2f_uart.h"

#include "multi_role.h"
// extern signed char mr_WriteData(unsigned short conhdl, \
//                     unsigned short writehdl, 
//                       unsigned char *data, unsigned short len);
// extern void Multi_BLESend(void);

#define S_OPENDOOR_CTL_BLE_ADDR_LEN             6
#define S_OPENDOOR_CTL_NORMALDATA_LEN           5

#define S_OPENDOOR_CTL_BLE_EACHDATA_LEN			20

typedef enum
{
    s_opendoor_order_default = 0,
    s_opendoor_order_getrandom,
    s_opendoor_order_sendsigned,
    s_opendoor_order_sendfinished
}s_opendoor_order_t;

static const unsigned char s_opendoor_bleaddr[] = {0x89, 0x03, 0x00, 0x00, 0x00, 0x10};
// static const unsigned char s_opendoor_bleaddr[] = {0x99, 0x99, 0x66, 0x66, 0x99, 0x98};
//static const unsigned char s_opendoor_bleaddr[] = {0x32, 0x00, 0x00, 0x00, 0x00, 0x10};

static unsigned char s_opendoor_uprandom[12] = {'R', 'C', 'U', 'R'};
#define S_OPENDOOR_UPRANDOM_DATA_INDEX          4
#define S_OPENDOOR_UPRANDOM_DATA_LENGTH         (sizeof(s_opendoor_uprandom) / sizeof(unsigned char))

#define S_OPENDOOR_BLESENDDATA_LEN  			256

#define S_OPENDOOR_CHECKSIGNEDDATA_INDEX		4

static const unsigned char s_opendoor_getrandom[] = {0x00, 0x84, 0x00, 0x00, 0x08};
static unsigned char s_opendoor_checksigneddata[] = {0x00, 0x90, 0x00, 0x00};

static unsigned char s_opendoor_blesenddata[S_OPENDOOR_BLESENDDATA_LEN];

static unsigned short s_opendoor_blesenddatacount = 0U;
static unsigned short s_opendoor_blesenddatalength = 0U;

//signed char S_OpenDoor_CompareBLEAddr(const unsigned char *addrneed, \
//                                   const unsigned char *addrfound)
//{
//    return 0;
//}

typedef struct
{
	unsigned char mac[S_OPENDOOR_CTL_BLE_ADDR_LEN];
	unsigned char mactype;
	unsigned char devIndex;
	unsigned short connHdl;
	unsigned short charHdl;
	unsigned short writeHdl;
	unsigned short readHdl;
	unsigned short notiHdl;
	s_opendoor_order_t order;
}s_opendoor_t;

static s_opendoor_t s_opendoor_data_t;

s_opendoor_status S_OpenDoor_Data_Init(void)
{

	s_opendoor_data_t.devIndex = 0U;
	s_opendoor_data_t.charHdl = 0U;
	s_opendoor_data_t.writeHdl = 0U;//0x1E;//0U;
	s_opendoor_data_t.readHdl = 0U;
	s_opendoor_data_t.notiHdl = 0U;//0x1F;//0U;
	s_opendoor_data_t.connHdl = 0U;

	S_OpenDoor_Updata_MAC(s_opendoor_bleaddr);

	return s_opendoor_ok;
}

s_opendoor_status S_OpenDoor_CompareSpecialBLEAddr(const unsigned char *addr)
{
    if(memcmp(addr, s_opendoor_bleaddr, S_OPENDOOR_CTL_BLE_ADDR_LEN))
    {
        return s_opendoor_addr_notmatch;
    }
    else
    {
//        printf("BLE addr correct\r\n");
        return s_opendoor_ok;
    }
}

s_opendoor_status S_OpenDoor_RecordDevIndex(unsigned char index)
{
    index = 0U;
//    printf("The index is %d\r\n", index);
	s_opendoor_data_t.devIndex = index;
	return s_opendoor_ok;
}

unsigned char S_OpenDoor_GetDevIndex(void)
{
	return s_opendoor_data_t.devIndex;
}

s_opendoor_status S_OpenDoor_RecordConnHdl(unsigned short hdl)
{
//    printf("The connhdl is %d\r\n", hdl);
    s_opendoor_data_t.connHdl = hdl;
    return s_opendoor_ok;
}

unsigned short S_OpenDoor_GetConnHdl(void)
{
    return s_opendoor_data_t.connHdl;
}

s_opendoor_status S_OpenDoor_RecordCharHdl(unsigned short hdl)
{
	printf("Record charHdl: 0x%02x\r\n", hdl);
	s_opendoor_data_t.charHdl = hdl;

	/*
		TODO
	*/
	s_opendoor_data_t.writeHdl = hdl;
	s_opendoor_data_t.notiHdl = hdl + 1;

	return s_opendoor_ok;
}

unsigned short S_OpenDoor_GetNotiyHdl(void)
{
	return s_opendoor_data_t.notiHdl;
}

unsigned short S_OpenDoor_GetWriteHdl(void)
{
	return s_opendoor_data_t.writeHdl;
}

s_opendoor_status S_OpenDoor_BLETurnOnNotifySuccessHandle(void)
{
    s_opendoor_blesenddatacount = 0U;
    memcpy(s_opendoor_blesenddata, s_opendoor_getrandom, S_OPENDOOR_CTL_NORMALDATA_LEN);

    Multi_BLE_DoSend();

    return s_opendoor_ok;
}

s_opendoor_status S_OpenDoor_BLEWriteSuccessHandle(void)
{	
//    printf("--order %d\r\n", s_opendoor_data_t.order);

    if(s_opendoor_order_sendsigned == s_opendoor_data_t.order)
    {
        if(s_opendoor_blesenddatacount < s_opendoor_blesenddatalength)
        {
            s_opendoor_blesenddatacount += S_OPENDOOR_CTL_BLE_EACHDATA_LEN;
            Multi_BLE_DoSend();
        }
        else
        {
//            printf("--change to order default\r\n");
            s_opendoor_data_t.order = s_opendoor_order_sendfinished;
        }
    }


	return s_opendoor_ok;
}

s_opendoor_status S_OpenDoor_BLEGetNotifyHandle(const unsigned char *data, unsigned short length)
{

    printf("Get notify data\r\n");
    debug_hex(data, length);

    if(s_opendoor_order_getrandom == s_opendoor_data_t.order)
    {
        s_opendoor_data_t.order = s_opendoor_order_sendsigned;

        memcpy(&s_opendoor_uprandom[S_OPENDOOR_UPRANDOM_DATA_INDEX], data, 8);

        H_CC2640R2F_UART_TxBuff(s_opendoor_uprandom, S_OPENDOOR_UPRANDOM_DATA_LENGTH);
    }
    else if(s_opendoor_order_sendfinished == s_opendoor_data_t.order)
    {
        Multi_BLE_DoDisconnect();
        s_opendoor_data_t.order = s_opendoor_order_default;
    }

    return s_opendoor_ok;
}

s_opendoor_status S_OpenDoor_SendCheckSignedData(unsigned char *data, unsigned short length)
{
    if(s_opendoor_order_sendsigned == s_opendoor_data_t.order)
    {
        // Msg head
        memcpy(s_opendoor_blesenddata, s_opendoor_checksigneddata, S_OPENDOOR_CHECKSIGNEDDATA_INDEX);
        // Check signed data
        memcpy(&s_opendoor_blesenddata[S_OPENDOOR_CHECKSIGNEDDATA_INDEX], data, length);

        s_opendoor_blesenddatacount = 0U;
        s_opendoor_blesenddatalength = length + S_OPENDOOR_CHECKSIGNEDDATA_INDEX;

        Multi_BLE_DoSend();
    }


	return s_opendoor_ok;
}

unsigned char *S_OpenDoor_SendCheckSignedData_Point(void)
{
//    debug_hex(&s_opendoor_blesenddata[s_opendoor_blesenddatacount], 10);
//    printf("The count is %d\r\n", s_opendoor_blesenddatacount);
	return (&s_opendoor_blesenddata[s_opendoor_blesenddatacount]);
}

unsigned short S_OpenDoor_SendCheckSignedData_Length(void)
{
    if(s_opendoor_order_getrandom == s_opendoor_data_t.order)
    {
        return S_OPENDOOR_CTL_NORMALDATA_LEN;
    }
    else if(s_opendoor_order_sendsigned == s_opendoor_data_t.order)
    {
//        if(s_opendoor_blesenddatacount + S_OPENDOOR_CTL_BLE_EACHDATA_LEN < s_opendoor_blesenddatalength)
//        {
//            s_opendoor_blesenddatacount += S_OPENDOOR_CTL_BLE_EACHDATA_LEN;
//            return S_OPENDOOR_CTL_BLE_EACHDATA_LEN;
//        }
//        else
//        {
//            return s_opendoor_blesenddatalength - s_opendoor_blesenddatacount;
//        }
        if(s_opendoor_blesenddatacount < s_opendoor_blesenddatalength)
        {
            printf("--len %d\r\n", S_OPENDOOR_CTL_BLE_EACHDATA_LEN);
            return S_OPENDOOR_CTL_BLE_EACHDATA_LEN;
        }
        else
        {
            printf("--len %d\r\n", s_opendoor_blesenddatalength + S_OPENDOOR_CTL_BLE_EACHDATA_LEN - s_opendoor_blesenddatacount);
            return (s_opendoor_blesenddatalength + S_OPENDOOR_CTL_BLE_EACHDATA_LEN - s_opendoor_blesenddatacount);
        }

    }
}

s_opendoor_status S_OpenDoor_Updata_MAC(const unsigned char *mac)
{
	unsigned char i = 0;
	unsigned char *tmp_mac = mac;
	while(i++ < S_OPENDOOR_CTL_BLE_ADDR_LEN)
	{
		if(*tmp_mac++ != 0x00)
		{
			printf("MAC legal\r\n");
			memcpy(s_opendoor_data_t.mac, \
					mac, S_OPENDOOR_CTL_BLE_ADDR_LEN);
			return s_opendoor_ok;
		}
	}

	return s_opendoor_data_illegal;
}

s_opendoor_status S_OpenDoor_Updata_MACType(unsigned char type)
{
	s_opendoor_data_t.mactype = type;
	return s_opendoor_ok;
}

unsigned char *S_OpenDoor_Get_MAC(void)
{
	return s_opendoor_data_t.mac;
}

unsigned char S_OpenDoor_Get_MACType(void)
{
	return s_opendoor_data_t.mactype;
}

/*
	If there is legal mac address, connect directly, 
	else do scan operation
*/
s_opendoor_status S_OpenDoor_Connect_Search(void)
{
    s_opendoor_data_t.order = s_opendoor_order_getrandom;
	/* No handle here, re-connect */
	if(0U == s_opendoor_data_t.writeHdl || \
		0U == s_opendoor_data_t.notiHdl)
	{
//		printf("Multi_BLE_DoConnect_Search\r\n");
		Multi_BLE_DoConnect_Search();
	}
	/* BLE handle with not-zero data */
	else
	{
//		printf("Multi_BLE_DoConnect\r\n");
		Multi_BLE_DoConnect();
	}
}
